/**
 * BLE设备管理器
 * 处理低功耗蓝牙设备的连接、断开等操作
 */

import { bluetoothCore } from '../utils/core.js'
import { 
  createError, 
  createSuccess, 
  formatDeviceInfo,
  checkRequiredParams,
  withTimeout,
  checkDeviceBLECompatibility,
  analyzeConnectionError
} from '../utils/utils.js'
import { 
  ERROR_CODES, 
  CONNECTION_STATE, 
  DEFAULT_CONFIG,
  PLATFORMS
} from '../utils/constants.js'

/**
 * BLE设备管理器类
 */
export class BLEDeviceManager {
  constructor() {
    this.platform = bluetoothCore.platform
    this.isH5 = bluetoothCore.isH5
    this.connectedDevices = new Map()
    this.connectionPromises = new Map()
  }

  /**
   * 连接低功耗蓝牙设备
   */
  async createBLEConnection(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId'])
      
      const { deviceId } = options
      
      // 检查蓝牙适配器是否已初始化
      if (!bluetoothCore.state.adapterInitialized) {
        return createError(ERROR_CODES.BLUETOOTH_NOT_INIT, '蓝牙适配器未初始化，请先初始化蓝牙适配器')
      }
      
      // 检查是否已经连接
      if (this.connectedDevices.has(deviceId)) {
        const device = this.connectedDevices.get(deviceId)
        if (device.connectionState === CONNECTION_STATE.CONNECTED) {
          return createSuccess({ message: 'Device already connected' })
        }
      }

      // 检查是否正在连接中
      if (this.connectionPromises.has(deviceId)) {
        return await this.connectionPromises.get(deviceId)
      }

      // 创建连接Promise
      const connectionPromise = this.isH5 ? 
        this._createBLEConnectionH5(options) : 
        this._createBLEConnectionNative(options)

      this.connectionPromises.set(deviceId, connectionPromise)

      try {
        const result = await withTimeout(connectionPromise, options.timeout || DEFAULT_CONFIG.CONNECTION_TIMEOUT)
        return result
      } finally {
        this.connectionPromises.delete(deviceId)
      }
    } catch (error) {
      console.error('[JZ-H5-Bluetooth] Connection error:', error)
      return createError(ERROR_CODES.CONNECTION_FAIL, `连接设备失败: ${error.message}`)
    }
  }

  /**
   * H5平台连接BLE设备
   */
  async _createBLEConnectionH5(options) {
    const { deviceId } = options
    let device = null // 在外层作用域声明device变量
    
    try {
      // 从缓存中获取设备对象
      device = bluetoothCore.state.devices.get(deviceId)
      
      // 如果直接找不到，尝试遍历查找（处理ID格式不一致的情况）
      if (!device) {
        for (const [cachedId, cachedDevice] of bluetoothCore.state.devices) {
          if (cachedId === deviceId || cachedDevice.id === deviceId) {
            device = cachedDevice
            break
          }
        }
      }
      
      if (!device) {
        console.error('[JZ-H5-Bluetooth] Device not found in cache:', deviceId)
        console.error('[JZ-H5-Bluetooth] Cached devices:', Array.from(bluetoothCore.state.devices.keys()))
        return createError(ERROR_CODES.DEVICE_NOT_FOUND, `设备未找到：设备 ${deviceId} 不在缓存中，请重新选择设备`)
      }

      // 进行设备兼容性检查
      const compatibilityCheck = checkDeviceBLECompatibility(device)
      
      if (!compatibilityCheck.compatible) {
        let errorMessage = `设备不兼容：${compatibilityCheck.reason}`
        if (compatibilityCheck.suggestions.length > 0) {
          errorMessage += '\n\n建议：\n' + compatibilityCheck.suggestions.join('\n')
        }
        
        // 根据设备类型选择合适的错误码
        const errorCode = compatibilityCheck.deviceType === 'audio-device' || compatibilityCheck.deviceType === 'classic-bluetooth' 
          ? ERROR_CODES.WEB_BLUETOOTH_NOT_SUPPORTED 
          : ERROR_CODES.CONNECTION_FAIL
          
        return createError(errorCode, errorMessage)
      }

      // 检查设备是否支持GATT
      if (!device.gatt) {
        return createError(ERROR_CODES.CONNECTION_FAIL, '设备不支持GATT：该设备不支持低功耗蓝牙连接')
      }

      // 检查GATT服务器是否可用
      if (device.gatt.connected) {
        this._setDeviceConnectionState(deviceId, CONNECTION_STATE.CONNECTED, { device, server: device.gatt })
        return createSuccess({ message: 'Device already connected via GATT' })
      }

      // 设置连接状态
      this._setDeviceConnectionState(deviceId, CONNECTION_STATE.CONNECTING)

      // 连接GATT服务器
      const server = await device.gatt.connect()
      
      // 监听断开连接事件
      device.addEventListener('gattserverdisconnected', () => {
        this._handleDeviceDisconnected(deviceId)
      })

      // 更新连接状态
      this._setDeviceConnectionState(deviceId, CONNECTION_STATE.CONNECTED, {
        device,
        server
      })

      return createSuccess()
    } catch (error) {
      console.error('[JZ-H5-Bluetooth] Connection failed:', error)
      this._setDeviceConnectionState(deviceId, CONNECTION_STATE.DISCONNECTED)
      
      // 首先检查是否是设备不支持的错误
      if (error.name === 'NetworkError' && error.message && error.message.includes('Unsupported device')) {
        // 确保device对象存在再进行分析
        const errorAnalysis = device ? analyzeConnectionError(error, device) : {
          errorType: 'unsupported-device',
          userFriendlyMessage: '设备不兼容：此设备不支持BLE连接',
          suggestions: [
            '该设备可能是蓝牙耳机、音箱等音频设备',
            'Web Bluetooth API不支持经典蓝牙设备',
            '请尝试连接支持BLE的设备：智能手环、传感器等',
            '如果确需连接音频设备，请考虑使用原生App平台'
          ]
        }
        
        let detailedMessage = errorAnalysis.userFriendlyMessage
        if (errorAnalysis.suggestions && errorAnalysis.suggestions.length > 0) {
          detailedMessage += '\n\n解决方案：\n' + errorAnalysis.suggestions.join('\n')
        }
        
        return createError(
          ERROR_CODES.WEB_BLUETOOTH_NOT_SUPPORTED, 
          detailedMessage
        )
      } else if (error.name === 'NetworkError') {
        return createError(ERROR_CODES.CONNECTION_FAIL, '网络错误：设备连接失败，请检查设备是否在范围内并重试')
      } else if (error.name === 'NotFoundError') {
        return createError(ERROR_CODES.DEVICE_NOT_FOUND, '设备不可用：设备可能已关闭或超出范围，请重新选择设备')
      } else if (error.name === 'SecurityError') {
        return createError(ERROR_CODES.PERMISSION_DENIED, '权限被拒绝：无法连接到设备，请检查浏览器权限设置')
      } else if (error.name === 'NotSupportedError') {
        return createError(ERROR_CODES.CONNECTION_FAIL, '不支持的操作：当前浏览器或设备不支持此连接方式')
      } else if (error.name === 'InvalidStateError') {
        return createError(ERROR_CODES.CONNECTION_FAIL, '设备状态无效：设备可能正在被其他应用使用，请稍后重试')
      } else if (error.name === 'AbortError') {
        return createError(ERROR_CODES.CONNECTION_FAIL, '连接被中断：请重新尝试连接设备')
      } else if (error.name === 'TimeoutError') {
        return createError(ERROR_CODES.CONNECTION_TIMEOUT, '连接超时：设备响应时间过长，请检查设备状态并重试')
      } else if (error.message && error.message.includes('GATT operation')) {
        return createError(ERROR_CODES.CONNECTION_FAIL, 'GATT服务错误：设备连接异常，请重新选择并连接设备')
      } else if (error.message && error.message.includes('操作超时')) {
        return createError(ERROR_CODES.CONNECTION_TIMEOUT, error.message)
      } else {
        return createError(ERROR_CODES.CONNECTION_FAIL, `设备连接失败: ${error.message || '未知错误'}`)
      }
    }
  }

  /**
   * 原生平台连接BLE设备
   */
  async _createBLEConnectionNative(options) {
    return new Promise((resolve) => {
      uni.createBLEConnection({
        ...options,
        success: (res) => {
          this._setDeviceConnectionState(options.deviceId, CONNECTION_STATE.CONNECTED)
          resolve(createSuccess(res))
        },
        fail: (err) => {
          this._setDeviceConnectionState(options.deviceId, CONNECTION_STATE.DISCONNECTED)
          resolve(createError(err.errCode || ERROR_CODES.CONNECTION_FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 断开与低功耗蓝牙设备的连接
   */
  async closeBLEConnection(options = {}) {
    try {
      checkRequiredParams(options, ['deviceId'])
      
      const { deviceId } = options

      if (!this.connectedDevices.has(deviceId)) {
        return createError(ERROR_CODES.NOT_CONNECTED)
      }

      if (this.isH5) {
        return await this._closeBLEConnectionH5(options)
      } else {
        return await this._closeBLEConnectionNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台断开BLE连接
   */
  async _closeBLEConnectionH5(options) {
    const { deviceId } = options
    
    try {
      const deviceInfo = this.connectedDevices.get(deviceId)
      if (deviceInfo && deviceInfo.server) {
        this._setDeviceConnectionState(deviceId, CONNECTION_STATE.DISCONNECTING)
        deviceInfo.server.disconnect()
      }
      
      this._setDeviceConnectionState(deviceId, CONNECTION_STATE.DISCONNECTED)
      return createSuccess()
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * 原生平台断开BLE连接
   */
  async _closeBLEConnectionNative(options) {
    return new Promise((resolve) => {
      uni.closeBLEConnection({
        ...options,
        success: (res) => {
          this._setDeviceConnectionState(options.deviceId, CONNECTION_STATE.DISCONNECTED)
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 根据uuid获取处于已连接状态的设备
   */
  async getConnectedBluetoothDevices(options = {}) {
    try {
      if (this.isH5) {
        return await this._getConnectedBluetoothDevicesH5(options)
      } else {
        return await this._getConnectedBluetoothDevicesNative(options)
      }
    } catch (error) {
      return createError(ERROR_CODES.FAIL, error.message)
    }
  }

  /**
   * H5平台获取已连接设备
   */
  async _getConnectedBluetoothDevicesH5(options) {
    const connectedDevices = []
    
    for (const [deviceId, deviceInfo] of this.connectedDevices) {
      if (deviceInfo.connectionState === CONNECTION_STATE.CONNECTED) {
        const device = bluetoothCore.state.devices.get(deviceId)
        if (device) {
          connectedDevices.push(formatDeviceInfo(device, this.platform))
        }
      }
    }

    // 如果指定了services过滤条件
    if (options.services && options.services.length > 0) {
      // H5平台无法直接通过UUID过滤，返回所有已连接设备
      console.warn('H5 platform does not support filtering by services in getConnectedBluetoothDevices')
    }

    return createSuccess({ devices: connectedDevices })
  }

  /**
   * 原生平台获取已连接设备
   */
  async _getConnectedBluetoothDevicesNative(options) {
    return new Promise((resolve) => {
      uni.getConnectedBluetoothDevices({
        ...options,
        success: (res) => {
          // 更新本地连接状态
          res.devices.forEach(device => {
            this._setDeviceConnectionState(device.deviceId, CONNECTION_STATE.CONNECTED)
          })
          resolve(createSuccess(res))
        },
        fail: (err) => {
          resolve(createError(err.errCode || ERROR_CODES.FAIL, err.errMsg))
        }
      })
    })
  }

  /**
   * 获取设备连接状态
   */
  getDeviceConnectionState(deviceId) {
    const deviceInfo = this.connectedDevices.get(deviceId)
    return deviceInfo ? deviceInfo.connectionState : CONNECTION_STATE.DISCONNECTED
  }

  /**
   * 检查设备是否已连接
   */
  isDeviceConnected(deviceId) {
    return this.getDeviceConnectionState(deviceId) === CONNECTION_STATE.CONNECTED
  }

  /**
   * 获取所有已连接设备ID
   */
  getConnectedDeviceIds() {
    const connectedIds = []
    for (const [deviceId, deviceInfo] of this.connectedDevices) {
      if (deviceInfo.connectionState === CONNECTION_STATE.CONNECTED) {
        connectedIds.push(deviceId)
      }
    }
    return connectedIds
  }

  /**
   * 设置设备连接状态
   */
  _setDeviceConnectionState(deviceId, state, data = {}) {
    const existingInfo = this.connectedDevices.get(deviceId) || {}
    
    this.connectedDevices.set(deviceId, {
      ...existingInfo,
      ...data,
      connectionState: state,
      lastUpdateTime: Date.now()
    })

    // 如果断开连接，清理相关数据
    if (state === CONNECTION_STATE.DISCONNECTED) {
      // 从核心状态中移除
      bluetoothCore.state.connectedDevices.delete(deviceId)
      // 清理服务和特征值缓存
      this._clearDeviceCache(deviceId)
    } else if (state === CONNECTION_STATE.CONNECTED) {
      // 添加到核心状态
      bluetoothCore.state.connectedDevices.set(deviceId, this.connectedDevices.get(deviceId))
    }
  }

  /**
   * 处理设备断开连接事件
   */
  _handleDeviceDisconnected(deviceId) {
    // Device disconnected
    this._setDeviceConnectionState(deviceId, CONNECTION_STATE.DISCONNECTED)
    
    // 触发断开连接事件
    this._triggerDisconnectionEvent(deviceId)
  }

  /**
   * 触发断开连接事件
   */
  _triggerDisconnectionEvent(deviceId) {
    // 这里可以添加事件触发逻辑
    // 比如通知UI或其他组件设备已断开连接
  }

  /**
   * 清理设备缓存
   */
  _clearDeviceCache(deviceId) {
    // 清理服务缓存
    for (const [key, value] of bluetoothCore.state.services) {
      if (key.startsWith(deviceId)) {
        bluetoothCore.state.services.delete(key)
      }
    }
    
    // 清理特征值缓存
    for (const [key, value] of bluetoothCore.state.characteristics) {
      if (key.startsWith(deviceId)) {
        bluetoothCore.state.characteristics.delete(key)
      }
    }
  }

  /**
   * 清理所有连接
   */
  async disconnectAll() {
    try {
      const disconnectPromises = []
      const connectedDeviceIds = this.getConnectedDeviceIds()
      
      for (const deviceId of connectedDeviceIds) {
        disconnectPromises.push(this.closeBLEConnection({ deviceId }))
      }
      
      if (disconnectPromises.length > 0) {
        const results = await Promise.all(disconnectPromises)
      }
      
      this.connectedDevices.clear()
      
      return createSuccess({ 
        message: `Disconnected ${connectedDeviceIds.length} device(s)`,
        disconnectedDevices: connectedDeviceIds 
      })
    } catch (error) {
      console.error('[JZ-H5-Bluetooth] Disconnect all failed:', error)
      return createError(ERROR_CODES.FAIL, `Failed to disconnect all devices: ${error.message}`)
    }
  }

  /**
   * 重置设备管理器
   */
  reset() {
    this.connectedDevices.clear()
    this.connectionPromises.clear()
  }
}

// 导出单例实例
export const bleDeviceManager = new BLEDeviceManager() 